﻿using Nx;
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;

namespace Nx.UI
{
    public class PropertyChangedBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
        protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
        {
            OnPropertyChanged(PropertyName(propertyExpression));
        }

        protected static string PropertyName<T>(Expression<Func<T>> propertyExpression)
        {
            Condition.Require<ArgumentNullException>(propertyExpression == null, "propertyExpression");            

            var memberExpression = propertyExpression.Body as MemberExpression;

            Condition.Require<ArgumentException>(memberExpression == null, "The expression is not a member access expression.");
            
            var property = memberExpression.Member as PropertyInfo;

            Condition.Require<ArgumentException>(property == null, "The member access expression does not access a property.");
            
            var getMethod = property.GetGetMethod(true);

            Condition.Require<ArgumentException>(getMethod == null, "The referenced property does not have a get method.");            
            Condition.Require<ArgumentException>(getMethod.IsStatic, "The referenced property is a static property.");
            
            return memberExpression.Member.Name;
        }
    }
}
